import { store } from "../index.js";
import { defineStore } from "pinia";
import { ElLoading, ElMessage, ElMessageBox } from "element-plus";
import { useDetectionStoreHook } from "./detection";
import { useInfoStoreHook } from "./info";

let cardReading = false;

function max(arr) {
  let result = -9999;
  arr.forEach((item) => {
    if (item > result) result = item;
  });
  return result;
}

function min(arr) {
  let result = 9999;
  arr.forEach((item) => {
    if (item < result) result = item;
  });
  return result;
}

export const useSerialsStore = defineStore("scan", {
  state: () => ({
    qrCode: null,
    autoReport: true,
    available: [],
    list: [
      {
        tag: "measure", // 标记串口在store里的键名
        name: "1号量仪接口",
        port: "",
        baud: "9600",
        stopBit: "1",
        dataBit: "8",
        parity: "none",
        iconName: "icon-measure-connect"
      },
      {
        tag: "measure2",
        name: "2号量仪接口",
        port: "",
        baud: "9600",
        stopBit: "1",
        dataBit: "8",
        parity: "none"
      },
      {
        tag: "measure3",
        name: "3号量仪接口",
        port: "",
        baud: "9600",
        stopBit: "1",
        dataBit: "8",
        parity: "none"
      },
      {
        tag: "cardReader",
        name: "读卡器接口",
        port: "",
        baud: "9600",
        stopBit: "1",
        dataBit: "8",
        parity: "none",
        iconName: "icon-card-connect"
      },
      {
        tag: "scanner",
        name: "扫码器接口",
        port: "",
        baud: "9600",
        stopBit: "1",
        dataBit: "8",
        parity: "none"
      }
    ]
  }),
  actions: {
    async getSerials() {
      const available = await window.api.getSerialPorts();
      this.available = available.map((ser) => {
        return {
          label: ser.friendlyName ?? ser.path,
          value: ser.path
        };
      });
    },

    measureAnalysis(data, measureNumber) {
      const detectionStore = useDetectionStoreHook();
      const srcData = data.split(",");
      const measures = detectionStore.measureFields;
      for (let i = 0; i < measures.length; i++) {
        // measures[i].value = null
        const chs = [];
        measures[i].channels.forEach((ch) => {
          // 判断通道是否有measure属性
          if (ch.measure) {
            if (ch.measure === measureNumber) {
              chs.push(ch.value);
            }
          } else {
            chs.push(ch);
          }
        });
        const chName = measures[i].name;
        if (!(chs && chs.length && chs.length > 0)) {
          // ElMessage.error(`${chName}属性通道配置有误！请联系管理员检查！`)
          continue;
        }
        const alg = measures[i].alg;
        if (alg === 1) {
          // alg为1时代表需要取指定通道中的最大值
          for (const ch of chs) {
            let val = -9999;
            if (srcData.length <= ch) {
              // ElMessage.error(`量仪数据无法取得"${chName}"通道"${ch}"的值！`);
              // break;
              console.log(`量仪数据无法取得"${chName}"通道"${ch}"的值！`);
            } else {
              const parseVal = parseFloat(srcData[ch]);
              if (isNaN(parseVal)) {
                // ElMessage.error(`量仪数据异常，"${chName}"通道值(${srcData[ch]})格式错误！`);
                // break;
                console.log(`量仪数据异常，"${chName}"通道值(${srcData[ch]})格式错误！`);
              } else {
                val = parseVal;
              }
            }
            if (measures[i].buff) {
              measures[i].buff.push(val);
            } else {
              measures[i].buff = [val];
            }
          }
          if (measures[i].buff?.length >= measures[i].channels?.length) {
            measures[i].value = max(measures[i].buff);
            if (measures[i].value === -9999) {
              measures[i].value = null;
              ElMessage.error(`量仪数据异常，"${chName}"通道值数据获取失败！`);
            }
            measures[i].buff = [];
          }
        } else if (alg === 2) {
          // alg为2时代表需要取指定通道中的最小值
          for (const ch of chs) {
            let val = 9999;
            if (srcData.length <= ch) {
              // ElMessage.error(`量仪数据长度小于设定通道数！`);
              // break;
              console.log(`量仪数据无法取得"${chName}"通道"${ch}"的值！`);
            } else {
              const parseVal = parseFloat(srcData[ch]);
              if (isNaN(parseVal)) {
                // ElMessage.error(`量仪数据异常，"${chName}"通道值(${srcData[ch]})格式错误！`);
                // break;
                console.log(`量仪数据异常，"${chName}"通道值(${srcData[ch]})格式错误！`);
              } else {
                val = parseVal;
              }
            }
            if (measures[i].buff) {
              measures[i].buff.push(val);
            } else {
              measures[i].buff = [val];
            }
          }
          if (measures[i].buff?.length >= measures[i].channels?.length) {
            measures[i].value = min(measures[i].buff);
            if (measures[i].value === 9999) {
              measures[i].value = null;
              ElMessage.error(`量仪数据异常，"${chName}"通道值数据获取失败！`);
            }
            measures[i].buff = [];
          }
        } else {
          const val = parseFloat(srcData[chs[0]]);
          if (!isNaN(val)) {
            measures[i].value = val;
          }
        }
      }
    },

    async openSerial(index) {
      if (index >= this.list.length) {
        ElMessage.error("串口索引异常，打开失败！");
        return;
      }
      const _ser = this.list[index];
      let _opened;
      if (!_ser.opened) {
        // 判断是否有其他端口占用
        for (let i = 0; i < this.list.length; i++) {
          if (i === index) continue;
          const used = this.list[i];
          if (used.port === _ser.port && used.opened) {
            ElMessage.error(`打开失败！串口已被<${used.name}>占用！`);
            return;
          }
        }
        if (!_ser.connection) {
          if (!_ser.port) {
            ElMessage.error("请先选择串口！");
            return;
          }
          if (!(await this.createSerial(index))) {
            ElMessage.error("串口打开失败");
            return;
          }
        }
        await _ser.connection.open();
        _opened = true;
      } else {
        await _ser.connection.close();
        
        _opened = false;
      }
      await window.api.setStore(_ser.tag, {
        port: _ser.port,
        baud: _ser.baud,
        stopBit: _ser.stopBit,
        dataBit: _ser.dataBit,
        parity: _ser.parity,
        opened: _opened
      });
    },

    async onMeasureRead(d, measureNumber) {
      const data = String.fromCharCode.apply(null, d);
      // 添加量仪数据接收监听
      this.measureAnalysis(data, measureNumber);
      const detectionStore = useDetectionStoreHook();
      // 判断数据是否全部录入完毕，避免多量仪接入的情况下数据获取不完整
      for (let i = 0; i < detectionStore.measureFields.length; i++) {
        const field = detectionStore.measureFields[i];
        // 存在未录入的字段则直接跳过，不进行提报
        if (field.value === undefined || field.value === null) return;
      }
      // 判断扫码器是否打开，已打开则启动扫码扫描零件二维码
      if (this.scanner?.opened) {
        await window.api.serialSend(this.scanner.serial, "LON\r\n");
        setTimeout(async () => {
          await window.api.serialSend(this.scanner.serial, "LOFF\r\n");
        }, 5000);
      } else {
        // 扫码器不打开的情况下，直接进行数据提报
        this.qrCode = this.qrCode ?? crypto.randomUUID().toString().split("-").join("");
        if (this.autoReport) {
          await detectionStore.insertData(this.qrCode);
          this.qrCode = null;
        }
      }
    },

    async onCardRead(data) {
      if (cardReading) return; // 读卡操作执行过程中防止用户重复刷卡
      cardReading = true;
      const checkChars = data.slice(0, 3);
      const validChars = data.slice(7, 11);
      if (checkChars[0] !== 0x04 || checkChars[1] !== 0x0c || checkChars[2] !== 0x02) {
        cardReading = false;
        return;
      }
      let nString = "";
      for (const item of validChars) {
        let n = item.toString(16);
        if (n.length === 1) n = "0" + n;
        nString = n + nString;
      }
      // eslint-disable-next-line no-undef
      const n = BigInt("0x" + nString);
      let result = null;
      const flag = n >> 31n;
      if (flag === 1n) {
        result = -((~n + 1n) & 0xffffffffn);
      } else {
        result = n & 0xffffffffn;
      }
      result = result.toString();
      const loading = ElLoading.service();
      const info = useInfoStoreHook();
      const res = await window.api.getUserIdByCardNumber(result.toString());
      if (res.code === 0) {
        info.username = res.data;
        await info.userLogin();
      } else if (res.code > 0 && res.code < 90) {
        ElMessageBox.alert(`卡号<${result.toString()}>尚未登记，请联系管理员处理`, "卡号异常", {
          type: "error"
        })
          .then(() => {})
          .catch(() => {});
      } else {
        ElMessage.error(res.msg);
      }
      loading.close();
      cardReading = false;
    },

    async onScannerRead(d) {
      const data = String.fromCharCode.apply(null, d);
      if (data.length > 64) {
        ElMessage.error("二维码数据长度超限，请检查二维码是否正确");
        return;
      }
      this.qrCode = data;
      if (this.autoReport) {
        await useDetectionStoreHook().insertData(this.qrCode);
        this.qrCode = null;
      }
    },

    async createSerial(index) {
      const ser = this.list[index];
      // 判断读卡器字符串结束标识
      let delimiter = "\r\n";
      if (ser.tag === "cardReader") delimiter = undefined;
      try {
        ser.connection = await window.api.createSerial({ ...ser, delimiter });
        ser.connection.onChange((flag) => {
          ser.opened = flag;
        });
        if (ser.tag === "measure") {
          ser.connection.onRead(async (d) => await this.onMeasureRead(d, 1));
        } else if (ser.tag === "measure2") {
          ser.connection.onRead(async (d) => await this.onMeasureRead(d, 2));
        } else if (ser.tag === "measure3") {
          ser.connection.onRead(async (d) => await this.onMeasureRead(d, 3));
        } else if (ser.tag === "cardReader") {
          ser.connection.onRead(async (d) => await this.onCardRead(d));
        } else if (ser.tag === "scanner") {
          ser.connection.onRead(async (d) => await this.onScannerRead(d));
        }
        ser.connection.onError((err) => {
          ElMessage.error(`${ser.name}: ${err}`);
        });
        return ser;
      } catch (error) {
        return false;
      }
    },

    async serialInit() {
      await this.getSerials();
      for (let i = 0; i < this.list.length; i++) {
        const ser = this.list[i];
        let config = await window.api.getStore(ser.tag);
        let _opened;
        if (config) {
          _opened = config.opened;
          delete config.opened;
          Object.assign(ser, { name: ser.name, ...config });
        }
        // if (!ser.port) {
        //   if (this.available.length > 0) {
        //     ser.port = this.available[0].value;
        //   }
        // }
        // await this.createSerial(i);
        // if (_opened && ser.connection) {
        //   await ser.connection.open();
        // }
        if (ser.port) {
          await this.createSerial(i);
          if (_opened && ser.connection) {
            await ser.connection.open();
          }
        }
      }
    }
  }
});

export function useSerialsStoreHook() {
  return useSerialsStore(store);
}
